home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
ulib
/
listdir.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
7KB
|
279 lines
/***********************************************************************
* $Id: listdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $
*
*. Copyright(c) 1993,1994 by T.C. Zhao
* All rights reserved.
*.
*
* Semi-portable directory reader with cache. All entries will be put
* into a structure list whose members are name and type.
***********************************************************************/
#if !defined(lint) && defined(F_ID)
char *id_dlist = "$Id: listdir.c,v 0.80 1994/02/24 09:48:11 zhao Exp $";
#endif
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <limits.h>
#include "ulib.h"
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#define FLEN_MAX 256 /* maximum filename length w/o directory */
/******************************************************************
* Read a directory on UNIX SysV like systems
*
*******************************************************************/
#include "unistd.h"
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
/** On Ultrix, scandir and alphasort are never decleard */
#if defined(__STRICT_ANSI__)
extern int scandir(const char *dir, struct dirent **[],
int (*select) (struct dirent *),
int (*howsort) (struct dirent **, struct dirent **));
extern int alphasort(struct dirent **, struct dirent **);
#endif /** GCC on Ultrix */
#define MAXFL (PATH_MAX + FLEN_MAX)
static const char *cpat; /* current pattern */
static const char *cdir; /* current working directory */
static char fname[MAXFL + 2];
static struct stat ffstat;
/******************************************************************
* Filter the filename before handing over to the "file is here" list
******************************************************************/
static int
SysV_fselect(struct dirent *f)
{
strcat(strcpy(fname, cdir), f->d_name);
stat(fname, &ffstat);
/* always keep directory */
return (ffstat.st_mode & S_IFDIR) || wildmat(f->d_name, cpat);
}
/*******************************************************************
* On entry, dir must be no zero and be terminated properly, i.e.,
* ends with /
*******************************************************************/
#ifndef M_DBG
#define Tfree free
#endif
static int
SysV_get_entries(const char *dir, const char *pat, Dirlist ** dirlist)
{
static struct dirent **dlist;
Dirlist *dl;
static int lastn;
cpat = pat;
cdir = dir;
/* free all memory used. If malloc wrapper is used, need to change Tfree */
if (dlist)
{
while (--lastn >= 0)
if (dlist[lastn])
Tfree(dlist[lastn]);
Tfree(dlist);
dlist = 0;
}
/** read dir */
if ((lastn = scandir(dir, &dlist, SysV_fselect, alphasort)) > 0)
{
int i;
unsigned long mode;
dl = *dirlist = (Dirlist *) malloc((lastn + 1) * sizeof(Dirlist));
for (i = 0; i < lastn; i++, dl++)
{
strcat(strcpy(fname, dir), dlist[i]->d_name);
stat(fname, &ffstat);
mode = ffstat.st_mode;
dl->name = strdup(dlist[i]->d_name);
dl->type = ((mode & S_IFDIR) == S_IFDIR) ? FT_DIR :
(((mode & S_IFREG) == S_IFREG) ? FT_FILE : FT_OTHER);
}
dl->name = 0; /* sentinel */
}
return lastn;
}
/********************************************************************
* The user routine.
*
* Get a list of files in directory, subject to pattern matching,
* and return the file list. Rescan will force a read even the requested
* directory is cached.
*
********************************************************************/
#define MAXCACHE 10
static char *lastdir[MAXCACHE], *lastpat[MAXCACHE];
static int lastn[MAXCACHE];
static Dirlist *dirlist[MAXCACHE];
/********************************************************************
* Check if a particular directory is cached
********************************************************************/
static int
is_cached(const char *dir, const char *pat, int *c)
{
int cached = 0, i = 0;
static int lastcache;
do
{
cached = lastpat[i] && lastdir[i] &&
strcmp(lastdir[i], dir) == 0 && strcmp(lastpat[i], pat) == 0 &&
(dirlist[i] && dirlist[i]->name);
*c = i++;
}
while (!cached && i < MAXCACHE);
/* search for the least used slot if not cached */
if (!cached)
*c = (++lastcache) % MAXCACHE;
lastcache = *c;
M_info("CheckDirCache", "%s is %s cached", dir, cached ? "" : "not");
return cached;
}
static void
free_dirlist(Dirlist * dl)
{
while (dl && dl->name)
{
free(dl->name);
dl->name = 0; /* important: signifies empty list */
dl++;
}
}
void
free_all_dirlist(void)
{
int i;
for (i = 0; i < MAXCACHE; i++)
{
free_dirlist(dirlist[i]);
dirlist[i] = 0;
}
}
/**********************************************************************
* The user callable routine to read a directory
*********************************************************************/
Dirlist *
get_dir_list(const char *dir, const char *pattern, int *n, int rescan)
{
int i, c;
const char *pat = pattern;
static char okdir[PATH_MAX + 1];
if (!dir || !*dir)
return 0;
if (!pat || !*pat)
pat = "*";
/* fix the directory on the fly */
i = strlen(strcpy(okdir, dir));
if (okdir[i - 1] != '/')
{
okdir[i] = '/';
okdir[++i] = '\0';
}
/* is_cached must go first to get correct cache location */
if (!is_cached(okdir, pat, &c) || rescan)
{
free_dirlist(dirlist[c]);
dirlist[c] = 0;
lastn[c] = SysV_get_entries(okdir, pat, &dirlist[c]);
StrReDup(lastpat[c], pat);
StrReDup(lastdir[c], okdir);
}
*n = lastn[c];
return dirlist[c];
}
/***********************************************************************
* Misc. routines related directory
**********************************************************************/
int
is_valid_dir(const char *name)
{
struct stat statbuf;
return (stat(name, &statbuf) == 0 &&
(statbuf.st_mode & S_IFDIR) == S_IFDIR);
}
/************************************************************************
* Remove all files, except directories from dir
***********************************************************************/
void
rm_all_files(const char *dir, const char *pat)
{
Dirlist *dl, *dls;
int n;
push_dir();
chdir(dir);
/* always re-read the directory entries */
dl = get_dir_list(dir, pat, &n, 1);
if (dl && n > 0)
{
for (dls = dl + n; --dls >= dl;)
{
if (dls->type == FT_FILE)
if (remove(dls->name))
perror(dls->name);
}
}
pop_dir();
free_dirlist(dl);
}
/************************************************************
* File modification time
***********************************************************/
unsigned long
f_mtime(const char *s)
{
struct stat fffstat;
stat(s, &fffstat);
return fffstat.st_mtime;
}